package com.imclient.server;

import java.util.ArrayList;

import com.imclient.headler.AbstractHeadler;
import com.imclient.listener.ReceiveListener;
import com.imclient.message.Message;
import com.imclient.net.ClientServer;
import com.imclient.type.ConnInfoType;
import com.imclient.type.HeaderType;

public abstract class HeadlerServer {

	private String host;

	private int port;

	private SendServer ss;

	private ReceiveServer rs;

	private ClientServer cs;

	private long keeplive = 120000;

	private long reConnectTime = 0L;

	private boolean mclose = false;

	public boolean isMclose() {
		return mclose;
	}

	public void setMclose(boolean mclose) {
		this.mclose = mclose;
	}

	public long getReConnectTime() {
		return reConnectTime;
	}

	public void setReConnectTime(long reConnectTime) {
		this.reConnectTime = reConnectTime;
	}

	public HeadlerServer(String host, int port) {
		this.host = host;
		this.port = port;
	}

	public void setHost(String host) {
		this.host = host;
	}

	public void setPort(int port) {
		this.port = port;
	}

	public long getKeeplive() {
		return keeplive;
	}

	public void setKeeplive(long keeplive) {
		this.keeplive = keeplive;
	}

	public abstract void connectInfo(ConnInfoType ct);

	private ArrayList<AbstractHeadler> headlers = new ArrayList<AbstractHeadler>();

	public void addHeadler(AbstractHeadler headler) {
		headlers.add(headler);
	}

	public void close() {
		isretry = false;
		this.setMclose(true);
		for (AbstractHeadler ah : headlers) {
			ah.close();
		}
		if (cs != null) {
			cs.close();
		}
	}

	private boolean isretry = false;

	public void setIsretry(boolean isretry) {
		this.isretry = isretry;
	}

	public boolean isIsretry() {
		return isretry;
	}

	synchronized void start() throws Exception {

		while (true) {
			if (mclose) {
				connectInfo(ConnInfoType.CONNECTOVER);
				throw new Exception();
			}
			connectInfo(ConnInfoType.STARTCONN);
			cs = new ClientServer(host, port);
			try {
				cs.start();
				rs = new ReceiveServer(cs.getIps(), new ReceiveListener() {
					@Override
					public void receiveMessage(Message msg) {
						for (AbstractHeadler ah : headlers) {
							if (ah.getPushType()
									.name()
									.equals(msg.getHeader(HeaderType.Type
											.name()))) {
								try {
									ah.receive(msg, HeadlerServer.this);
								} catch (Exception e) {
									e.printStackTrace();
								} finally {

								}
							}
						}
					}
				});
				connectInfo(ConnInfoType.CONNSUCCESS);
				ss = new SendServer(cs.getOps());
				rs.Receives();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
			}
			cs.close();
			if (!isretry && this.getReConnectTime() > 0) {
				connectInfo(ConnInfoType.CONNECTOVER);
				throw new Exception();
			} else {
				if (this.getReConnectTime() != 0) {
					connectInfo(ConnInfoType.NETBREAK);
				}
				for (AbstractHeadler ah : headlers) {
					ah.netBreak();
				}

				if (this.getReConnectTime() == 0) {
					connectInfo(ConnInfoType.CONNECTOVER);
					throw new Exception();
				}
				try {
					if (this.getReConnectTime() > 1000) {
						Thread.sleep(this.getReConnectTime());
					} else {
						Thread.sleep(HeadlerServer.this.getKeeplive() + 40000);
					}
					connectInfo(ConnInfoType.RECONNECT);
				} catch (InterruptedException e) {
					e.printStackTrace();
				} finally {

				}
			}
			if (mclose) {
				connectInfo(ConnInfoType.CONNECTOVER);
				throw new Exception();
			}
		}

	}

	public boolean SendMsg(Message msg) {
		if (mclose) {
			return false;
		}
		if (ss != null) {
			return ss.sendMessage(msg);
		}
		return false;
	}

}
